From 9ab94f20c200f7e79297b9cbb7d654b8fba67115 Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 2 Apr 2024 22:28:14 -0700 Subject: feat(badges): custom css --- src/routes/user/[user]/badges/+page.svelte | 495 +++++++++++++++-------------- 1 file changed, 254 insertions(+), 241 deletions(-) (limited to 'src/routes/user/[user]/badges/+page.svelte') diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index 8c9e5ebd..78b4cf3e 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -3,7 +3,7 @@ import { user, type User } from '$lib/Data/AniList/user'; import type { Badge } from '$lib/Database/userBadges'; // import { domToBlob } from 'modern-screenshot'; - import { onMount } from 'svelte'; + import { onDestroy, onMount } from 'svelte'; import HeadTitle from '$lib/Home/HeadTitle.svelte'; import { databaseTimeToDate, dateToInputTime, inputTimeToDatabaseTime } from '$lib/Utility/time'; import root from '$lib/Utility/root.js'; @@ -21,6 +21,8 @@ import FallbackImage from '$lib/FallbackImage.svelte'; import FallbackBadge from '$lib/FallbackBadge.svelte'; import { page } from '$app/stores'; + import type { UserPreferences } from '$lib/Database/userPreferences.js'; + import { browser } from '$app/environment'; // import { io } from 'socket.io-client'; export let data; @@ -51,6 +53,7 @@ let importReplies = false; let badger: Partial; let migrateMode = false; + let preferences: UserPreferences; $: categoryFilter = new URLSearchParams($page.url.searchParams).get('category'); @@ -87,6 +90,27 @@ badgesPromise = fetch(root(`/api/badges?id=${badger.id}`)); awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`)); + preferences = await (await fetch(root(`/api/preferences?id=${badger.id}`))).json(); + + if (preferences.badge_wall_css) { + const sanitise = (css: string) => + css + .replace(/\/\*[\s\S]*?\*\//g, '') + .replace(/<\/?[^>]+(>|$)/g, '') + .replace( + /(expression|javascript|vbscript|onerror|onload|onclick|onmouseover|onmouseout|onmouseup|onmousedown|onkeydown|onkeyup|onkeypress|onblur|onfocus|onsubmit|onreset|onselect|onchange|ondblclick):/gi, + '' + ) + .replace(/(behaviour|behavior|moz-binding|content):/gi, '') + .replace(/\s+/g, ' ') + .trim(); + const style = document.createElement('style'); + + style.dataset.badgeWall = 'true'; + style.innerHTML = sanitise(preferences.badge_wall_css); + + document.head.appendChild(style); + } if (data.user && !isId) { currentUserIdentity = userIdentity(data.user); @@ -103,6 +127,13 @@ } }); + onDestroy(() => { + if (browser) + Array.from(document.head.querySelectorAll('style')).forEach((style) => { + if (style.dataset.badgeWall) style.remove(); + }); + }); + // const fallback = (event: Event, image: string | undefined) => // setTimeout(() => ((event.target as HTMLImageElement).src = image || ''), 1000); @@ -417,270 +448,252 @@ {:then badgesResponse} {#if badgesResponse} - {#await badgesResponse.json()} + {#await badgesResponse.clone().json()} {:then ungroupedBadges} - {#await fetch(root(`/api/preferences?id=${badger.id}`))} - - - - {:then rawPreferences} - {#await rawPreferences.json()} - - - - {:then preferences} -
- {#await awcPromise then badges} - {#await badges.text() then text} - {@const parsedBadges = awcBadgesGrouped(text)} - - {#if parsedBadges.length > 0} - {#each parsedBadges as group} -
- - Anime Watching Club | - {group.group} - - -

- -

- {#each group.badges as badge} - - - - {/each} -
-
- -

- {/each} - {/if} - {/await} - {/await} - - {#if ungroupedBadges === null} - - - - {:else} - {@const groupedBadges = Object.entries(groupBadges(ungroupedBadges))} - - {#if isOwner} -

- - - - - +

- {#if editMode && isOwner} - {@const groups = groupedBadges - .map((group) => group[0]) - .filter((group) => group !== 'Uncategorised')} +

+ {#each group.badges as badge} + + + + {/each} +
+ -

+

+ {/each} + {/if} + {/await} + {/await} - {#if error} -

{error}

- {/if} + {#if ungroupedBadges === null} + + + + {:else} + {@const groupedBadges = Object.entries(groupBadges(ungroupedBadges))} + + {#if isOwner} +
+ + + + + + + {#if editMode && isOwner} + {@const groups = groupedBadges + .map((group) => group[0]) + .filter((group) => group !== 'Uncategorised')} + +

+ + {#if error} +

{error}

+ {/if} + + + + ({ + name: group, + url: '#', + onClick: () => { + const category = document.querySelector('input[name="category"]'); + + if (category instanceof HTMLInputElement) category.value = group; + } + }))} + header={false} + center={false} + > + - - - ({ - name: group, - url: '#', - onClick: () => { - const category = document.querySelector('input[name="category"]'); - - if (category instanceof HTMLInputElement) category.value = group; - } - }))} - header={false} - center={false} - > - - - - - - {#if selectedBadge} - {$locale().user.badges.editMode.or} - - {/if} - - - Must be full date and time, defaults to now if any fields empty - - {/if} -
- {/if} - -

- - {#if ungroupedBadges.length === 0} -

- No due.moe registered badges found for this user. e.preventDefault()} - title="This alert does not include AWC badges." - use:tooltip>? + + + {#if selectedBadge} + {$locale().user.badges.editMode.or} + -
+ {/if} + + + Must be full date and time, defaults to now if any fields empty + {/if} +
+ {/if} + +

+ + {#if ungroupedBadges.length === 0} +

+ {/if} + + {#each groupedBadges as [category, badges]} +
+ {category} - {#each groupedBadges as [category, badges]} -
- {category} - -

+

-

-
+ +
- {#if groupedBadges[groupedBadges.length - 1][0] !== category} -

- {/if} - {/each} + {#if groupedBadges[groupedBadges.length - 1][0] !== category} +

{/if} -

- {:catch} - Could not parse badges - {/await} - {:catch} - Could not fetch badges - {/await} + {/each} + {/if} + {:catch} Could not parse badges {/await} -- cgit v1.2.3